﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#ifndef __9F6807D0_2ADE_4656_A2AF_B2D65BA36F64__
#define __9F6807D0_2ADE_4656_A2AF_B2D65BA36F64__

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                            COM_MAP
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// declare interface map
//

#define XOS_DECLARE_COM_MAP() \
    const xos::_XOS_COM_INTERFACE_MAP_ENTRY * _xos_get_interface_entries();\
    xos::i_unknown * get_unknown();

//                                                                             COM_MAP
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// com query interface map
//

#define XOS_BEGIN_IMPL_COM_MAP( x ) \
    typedef x _xos_class;\
    \
    xos::i_unknown * x::get_unknown()\
    {\
        return ( xos::i_unknown* )( ( xos::xos_int )this + _xos_get_interface_entries()->dw );\
    }\
    const xos::_XOS_COM_INTERFACE_MAP_ENTRY * x::_xos_get_interface_entries()\
    {\
        T * pThis = static_cast< T * >( this ); \
        const xos::_XOS_COM_INTERFACE_MAP_ENTRY * pEntry = pThis->xos_com_interface_map_entry(0,0);\
        if( pEntry )\
        {\
            return pEntry;\
        }\
        const xos::_XOS_COM_INTERFACE_MAP_ENTRY _entries[] = {

#define XOS_BEGIN_COM_MAP( x ) \
    typedef x _xos_class;\
    \
    xos::i_unknown * get_unknown()\
    {\
        return ( xos::i_unknown* )( ( xos::xos_int )this + _xos_get_interface_entries()->dw );\
    }\
    const xos::_XOS_COM_INTERFACE_MAP_ENTRY * _xos_get_interface_entries()\
    {\
        T * pThis = static_cast< T * >( this ); \
        const xos::_XOS_COM_INTERFACE_MAP_ENTRY * pEntry = pThis->xos_com_interface_map_entry(0,0);\
        if( pEntry )\
        {\
            return pEntry;\
        }\
        const xos::_XOS_COM_INTERFACE_MAP_ENTRY _entries[] = {

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// entries
// 

#define XOS_COM_INTERFACE_ENTRY_IID( iid, x ) \
            { iid, xos_offsetofclass( x, _xos_class ), 0 },

#define XOS_COM_INTERFACE_ENTRY( x ) \
            { x##_id, xos_offsetofclass( x, _xos_class ), 0 },

#define XOS_COM_INTERFACE_ENTRY_MEMBER_IID( iid, m ) \
            { iid, 0, offsetof( _xos_class, m ) },

#define XOS_COM_INTERFACE_ENTRY_MEMBER( x, m ) \
            { x##_id, 0, offsetof( _xos_class, m ) },

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// end
// 

#define XOS_END_IMPL_COM_MAP() \
            { 0, 0, 0 } \
        }; \
        pEntry = pThis->xos_com_interface_map_entry(_entries,sizeof(_entries)/sizeof(_entries[0]));\
        return pEntry; \
    }

#define XOS_END_COM_MAP() XOS_END_IMPL_COM_MAP()

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                            OBJ_MAP
// 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// declare com object map
//

#define XOS_DECLARE_COM_OBJ_MAP( i_interface ) \
    int create( const char * pClsName, i_interface ** ppv );

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// begin
// 

#define XOS_BEGIN_IMPL_COM_OBJ_MAP( x, i_interface, iid ) \
    int x::create( const char * pClsName, i_interface ** ppv )\
    {\
        T * pThis = static_cast< T* >( this );\
        bool bHasCollect = pThis->xos_has_collect_class_name();\
        const char * lpszIID = iid;\
        int result = 1;\
        int ret = 0;

#define XOS_BEGIN_COM_OBJ_MAP( x, i_interface, iid ) \
    int create( const char * pClsName, i_interface ** ppv )\
    {\
        T * pThis = static_cast< T* >( this );\
        bool bHasCollect = pThis->xos_has_collect_class_name();\
        const char * lpszIID = iid;\
        int result = 1;\
        int ret = 0;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// entries
// 

// helper mac for prefix
#define _XOS_COM_OBJ_ENTRY_PREFIX( x, cls_name ) \
        if( !bHasCollect )\
        {\
            pThis->xos_collect_com_obj_class_name( cls_name );\
        }\
        if( ( 0 == ret ) && ( 0 == xos::xos_is_equal_interface_id( cls_name, pClsName ) ) )\
        {\
            x::T * pObj = x::T::get_item_from_pool( true );

// helper mac for suffix
#define _XOS_COM_OBJ_ENTRY_SUFFIX() \
            pObj->init();\
            result = pObj->query_interface( lpszIID, ( void** )ppv );\
            if( pThis->has_reference() )\
            {\
                pObj->release(); \
            }\
            ret = 1;\
        }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

// class name
#define XOS_COM_OBJ_ENTRY_NAME( x, cls_name ) \
        _XOS_COM_OBJ_ENTRY_PREFIX( x, cls_name )\
        _XOS_COM_OBJ_ENTRY_SUFFIX()

// no class name
#define XOS_COM_OBJ_ENTRY( x ) XOS_COM_OBJ_ENTRY_NAME( x, #x )

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

// agg with function
#define XOS_COM_OBJ_ENTRY_NAME_WITH_FUNCTION( x, cls_name, fun ) \
        _XOS_COM_OBJ_ENTRY_PREFIX( x, cls_name )\
            pObj->set_agged_function( #fun, fun );\
        _XOS_COM_OBJ_ENTRY_SUFFIX()

// no class name
#define XOS_COM_OBJ_ENTRY_WITH_FUNCTION( x, fun ) XOS_COM_OBJ_ENTRY_NAME_WITH_FUNCTION( x, #fun, fun )

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

// agg with obj
#define XOS_COM_OBJ_ENTRY_NAME_WITH_OBJ( x, cls_name, obj ) \
        _XOS_COM_OBJ_ENTRY_PREFIX( x, cls_name )\
            pObj->set_agged_obj( #obj, obj );\
        _XOS_COM_OBJ_ENTRY_SUFFIX()

// no class name
#define XOS_COM_OBJ_ENTRY_WITH_OBJ( x, obj ) XOS_COM_OBJ_ENTRY_NAME_WITH_OBJ( x, #obj, obj )

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

// agg with class
#define XOS_COM_OBJ_ENTRY_NAME_WITH_CLASS( x, cls_name, cls ) \
        _XOS_COM_OBJ_ENTRY_PREFIX( x, cls_name )\
            cls * pCls = new cls;\
            pCls->init();\
            pObj->set_agged_obj( #cls, pCls );\
        _XOS_COM_OBJ_ENTRY_SUFFIX()

// no class name
#define XOS_COM_OBJ_ENTRY_WITH_CLASS( x, cls ) XOS_COM_OBJ_ENTRY_NAME_WITH_CLASS( x, #cls, cls )

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

// agg with class and cached
#define XOS_COM_OBJ_ENTRY_NAME_WITH_CLASS_AND_CACHED( x, cls_name, cls ) \
        _XOS_COM_OBJ_ENTRY_PREFIX( x, cls_name )\
            cls * pCls = ( cls* )pObj->get_cached_obj( cls_name );\
            if( !pCls )\
            {\
                pCls = new cls;\
            }\
            pCls->init();\
            pObj->set_agged_obj( #cls, pCls );\
        _XOS_COM_OBJ_ENTRY_SUFFIX()

// no class name cached
#define XOS_COM_OBJ_ENTRY_WITH_CLASS_AND_CACHED( x, cls ) XOS_COM_OBJ_ENTRY_NAME_WITH_CLASS_AND_CACHED( x, #cls, cls )

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

// agg with pool class
#define XOS_COM_OBJ_ENTRY_NAME_WITH_POOL_CLASS( x, cls_name, cls ) \
        _XOS_COM_OBJ_ENTRY_PREFIX( x, cls_name )\
            cls::T * pCls = cls::T::get_item_from_pool( true );\
            pCls->init();\
            pObj->set_agged_obj( #cls, pCls );\
        _XOS_COM_OBJ_ENTRY_SUFFIX()

// no class name
#define XOS_COM_OBJ_ENTRY_WITH_POOL_CLASS( x, cls ) XOS_COM_OBJ_ENTRY_NAME_WITH_POOL_CLASS( x, #x, cls )

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// end
// 

#define XOS_END_IMPL_COM_OBJ_MAP() \
        return result;\
    }

#define XOS_END_COM_OBJ_MAP() XOS_END_IMPL_COM_OBJ_MAP()

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

#endif // __9F6807D0_2ADE_4656_A2AF_B2D65BA36F64__
